<?php
hc_core_ClassLoader::load('halo_IHandlerMapping');
hc_core_ClassLoader::load('halo_HandlerExecutionChain');
hc_core_ClassLoader::load('hc_core_ordered_IOrdered');
hc_core_ClassLoader::load('substrate_stones_IContextAware');
require_once('substrate_stones_IContextAware.php');
abstract class halo_AbstractHandlerMapping implements halo_IHandlerMapping, substrate_stones_IContextAware, hc_core_ordered_IOrdered {

    protected $context;
    protected $defaultHandler;
    protected $interceptors = array();
    protected $order = null;

    final public function getHandler(halo_HttpRequest $httpRequest) {

        $handler = $this->getHandlerInternal($httpRequest);
        if ( $handler === null ) {
            $handler = $this->defaultHandler;
        }
        if ( $handler === null ) {
            return null;
        }
        if ( is_string($handler) ) {
            //
        }
        return $handler;
    }

    public function informAboutContext(substrate_Context $context) {
        $this->context = $context;
        $this->initContext();
    }

    protected function initContext() {
        $this->extendInterceptors($this->interceptors);
        $this->initInterceptors();
    }

    protected function getAdaptedInterceptors() {
        return $this->adaptedInterceptors;
    }

    public function getHandlerExecutionChain(halo_HttpRequest $httpRequest) {
        $handler = $this->getHandler($httpRequest);
        if ( $handler !== null ) {
            return $this->getHandlerExecutionChainInternal($handler);
        }
        return null;
    }

    protected function getHandlerExecutionChainInternal($handler) {
        if ( $handler instanceof halo_HandlerExecutionChain ) {
            $handler->addInterceptors($this->getAdaptedInterceptors());
            return $handler;
        } else {
            return new halo_HandlerExecutionChain($handler, $this->getAdaptedInterceptors());
        }
    }

    public function setInterceptors($interceptors) {
        if ( ! is_array($interceptors) ) { $interceptors = array($interceptors); }
        foreach ( $interceptors as $interceptor ) {
            $this->interceptors[] = $interceptor;
        }
    }

    /**
      * Hook to allow for additional interceptors to be registred.
      */
    public function extendInterceptors($interceptors) {
    }

    public function initInterceptors() {
        $this->adaptedInterceptors = array();
        foreach ( $this->interceptors as $interceptor ) {
            if ( is_string($interceptor) ) {
                $interceptor = $this->context->get($interceptor);
            }
            $this->adaptedInterceptors[] = $this->adaptInterceptor($interceptor);
        }
    }

    public function adaptInterceptor($interceptor) {
        if ( $interceptor instanceof halo_IHandlerInterceptor ) {
            return $interceptor;
        //} elseif ( $interceptor instanceof halo_ISomethingElse ) {
            //return new halo_HandlerInterceptorInterfaceAdapter($interceptor);
        } else {
            throw new Exception('Interceptor of type "' . get_class($interceptor) . '" not supported.');
        }
    }

    public function getOrder() {
        return $this->order;
    }

    public function setOrder($order) {
        $this->order = $order;
    }

    abstract protected function getHandlerInternal(halo_HttpRequest $httpRequest);

}
?>
